package kr.salebeans.cm.process.sale.impl;

import org.springframework.beans.factory.annotation.Autowired;

import kr.salebeans.cm.domain.common.DataHandling;
import kr.salebeans.cm.domain.customer.Customer;
import kr.salebeans.cm.domain.point.CustomerPoint;
import kr.salebeans.cm.domain.point.PointClsType;
import kr.salebeans.cm.domain.sale.PaymentType;
import kr.salebeans.cm.domain.sale.Sale;
import kr.salebeans.cm.domain.shop.Shop;
import kr.salebeans.cm.process.sale.SaleProcess;
import kr.salebeans.cm.provider.customer.CustomerProvider;
import kr.salebeans.cm.provider.point.CustomerPointProvider;
import kr.salebeans.cm.provider.sale.SaleProvider;
import kr.salebeans.cm.provider.shop.ShopProvider;
import kr.salebeans.cm.sale.SaleRegisterDto;
import kr.salebeans.cm.sale.SaleRegisterReqDto;
import kr.salebeans.cm.sale.SaleRegisterResDto;
import kr.salebeans.cm.util.DateUtils;
import kr.salebeans.cm.util.StringUtils;

public class SaleProcessImpl implements SaleProcess {

    @Autowired
    private SaleProvider saleProvider;

    @Autowired
    private ShopProvider shopProvider;

    @Autowired
    private CustomerProvider customerProvider;

    @Autowired
    private CustomerPointProvider customerPointProvider;

    public void setCustomerPointProvider(CustomerPointProvider customerPointProvider) {
        this.customerPointProvider = customerPointProvider;
    }

    public void setCustomerProvider(CustomerProvider customerProvider) {
        this.customerProvider = customerProvider;
    }

    public void setShopProvider(ShopProvider shopProvider) {
        this.shopProvider = shopProvider;
    }

    public void setSaleProvider(SaleProvider saleProvider) {
        this.saleProvider = saleProvider;
    }

    private void validateSale(SaleRegisterReqDto saleReq) {
        if (saleReq == null || saleReq.getSale() == null) throw new RuntimeException("조회조건이 입력되지 않았습니다.");
        SaleRegisterDto saleRegDto = saleReq.getSale();
        // 철저한 회원제로감
        if (saleRegDto.getCustomerId() < 1) throw new RuntimeException("고객아이디가 입력되지 않았습니다.");
        // 고객 유뮤체크
        Customer customer = this.customerProvider.retrieveCustomer(saleRegDto.getCustomerId());
        if (customer == null) {
            throw new RuntimeException("고객아이디[" + saleRegDto.getCustomerId() + "] 에 해당하는 고객이 없습니다.");
        }
        // 결제유형 (1: 카드 2: 캐쉬)
        if (StringUtils.isBlank(saleRegDto.getPaymentType())) {
            throw new RuntimeException("결제유형이 입력되지 않았습니다.");
        }
        if (StringUtils.isBlank(saleRegDto.getShopId())) {
            throw new RuntimeException("샵아이디가 입력되지 않았습니다.");
        }
    }

    @Override
    public void modifySaleRemark(long saleId, String remark) {
        if (saleId < 1) {
            throw new RuntimeException("판매아이디가 존재하지 않습니다.");
        }

        if (StringUtils.isBlank(remark)) return;
        // #1. 판매조회
        Sale sale = this.saleProvider.retrieveSale(saleId);
        if (sale == null) {
            throw new RuntimeException("해당아이디" + saleId + "에 해당하는 판매가 존재하지 않습니다.");
        }
        sale.setRemark(remark);
        DataHandling handling = sale.getHandling();
        handling.setUpdateDateTime(DateUtils.getCurrentBaseDateString());

        this.saleProvider.updateSale(sale);
    }

    @Override
    public SaleRegisterResDto registerSale(SaleRegisterReqDto saleReq) {
        this.validateSale(saleReq);

        SaleRegisterDto saleRegDto = saleReq.getSale();
        if (saleRegDto.getSaleId() > 0) {
            throw new RuntimeException("판매아이디가 존재합니다. 수정으로 해주세요.");
        }

        // #1. 판매등록
        Sale sale = new Sale();
        sale.setShopId(saleRegDto.getShopId());
        sale.setCustomerId(saleRegDto.getCustomerId());
        sale.setSaleTypeId(saleRegDto.getSaleTypeId()); // 파마, 스트레이트 등 공통 아이디 없어도됨
        sale.setSaleAmount(saleRegDto.getSaleAmount()); // 0원 가능
        sale.setRemark(saleRegDto.getRemark());
        if ("1".equals(saleRegDto.getPaymentType())) {
            sale.setPaymentType(PaymentType.CARD);
        }
        else if ("2".equals(saleRegDto.getPaymentType())) {
            sale.setPaymentType(PaymentType.CASH);
        }
        else {
            throw new RuntimeException("잘못된 결제유형이 입력[" + saleRegDto.getPaymentType() + "]");
        }

        sale = this.saleProvider.createSale(sale);
        saleRegDto.setSaleId(sale.getId());

        // #2. 포인트 등록
        if (saleRegDto.getPoint() > 0) { // 포인트 입력시 입력된 포인트 우선
            CustomerPoint customerPorint = new CustomerPoint();
            customerPorint.setCustomerId(saleRegDto.getCustomerId());
            customerPorint.setPoint(saleRegDto.getPoint());
            customerPorint.setSaleId(sale.getId());
            customerPorint.setPointCls(PointClsType.PLUS);
            this.customerPointProvider.createCustomerPoint(customerPorint);
        }
        // 포인트 미 입력시 샵설정따른 포인트
        else if (saleRegDto.isAdjustPoint() && saleRegDto.getSaleAmount() > 0) {
            Shop shop = this.shopProvider.retriveShop(saleRegDto.getShopId());
            long pointRate = 0;
            if (sale.getPaymentType() == PaymentType.CARD) {
                pointRate = shop.getSettings().getCardPointRate();
            }
            else {
                pointRate = shop.getSettings().getCashPointRate();
            }

            long point = 0;
            if (pointRate > 0) {
                point = saleRegDto.getSaleAmount() * (pointRate / 100);
            }
            if (point < 1) point = 1;

            CustomerPoint customerPorint = new CustomerPoint();
            customerPorint.setCustomerId(saleRegDto.getCustomerId());
            customerPorint.setPoint(point);
            customerPorint.setSaleId(sale.getId());
            customerPorint.setPointCls(PointClsType.PLUS);
            this.customerPointProvider.createCustomerPoint(customerPorint);
        }
        SaleRegisterResDto res = new SaleRegisterResDto();
        res.setSale(saleRegDto);
        return res;
    }
}
